<?php
abstract class Arm_Form_Builder_Plugin_Abstract
{
    /**
     * Префикс для билиотеки Arm
     * 
     * @var string
     */
    private $_systemNameSpace = 'Arm';
    
    /**
     * Пространоство имен.
     * @var string
     */
    private $_nameSpace = null;
    
    /**
     * Данные для создания одного метода.
     * @var array
     */
    private $_data = array();
    
    /**
     * Имя Метода который создаем.
     * @var string
     */
    private $_nameMethod = null;
    
    /**
     * Имя элемената для которого создаем метод.
     * @var string
     */
    private $_nameElement = null;
    
	/**
     * @return the $_systemNameSpace
     */
    public function getSystemNameSpace ()
    {
        return $this->_systemNameSpace;
    }

	/**
     * @return the $_nameSpace
     */
    public function getNameSpace ()
    {
        return $this->_nameSpace;
    }

	/**
     * @return the $_data
     */
    public function getData ()
    {
        return $this->_data;
    }

	/**
     * @param $_systemNameSpace the $_systemNameSpace to set
     */
    public function setSystemNameSpace ($systemNameSpace)
    {
        $this->_systemNameSpace = ucfirst(strtolower($systemNameSpace));
    }

	/**
     * @param $_nameSpace the $_nameSpace to set
     */
    public function setNameSpace ($nameSpace)
    {
        $this->_nameSpace = ucfirst(strtolower($nameSpace));
    }

	/**
     * @param $_data the $_data to set
     */
    public function setData ($data)
    {
        $this->_data = $data;
    }
    
    /**
     * Установит имя метода который нужно создать, и названия элемента.
     * @param string $name
     */
    public function setNameMethod($nameElement)
    {
       $nameElement  = strtolower($nameElement);
       // добавим вторую часть таблицы. если существует.
            if (isset($this->_data['TABLE_NAME'])!== false) {
                $table = explode('_', $this->_data['TABLE_NAME']);
                $nameElement = $table[1] . '_' . $nameElement;
            }
       $array = explode('_', $nameElement);
       $str   = ''; 
            for ($i=0; $i<count($array); $i++) {
                    if (0 === $i) {
                        $str .= $array[0];
                        continue;
                    }
                $str .= ucfirst($array[$i]);
            }
       $this->_nameMethod = $str;
       return;
    }
    
    
    /**
     * Установка имени элемента
     * @param string $name
     */
    public function setNameElement($name)
    {
        $this->_nameElement  = $name;
    }
    
    
    /**
     * Вернет имя метода который нужно создать. 
     * 
     * @return string
     */
    public function getNameMethod()
    {
        return $this->_nameMethod;
    }
    
    /**
     * Имя элемента для которого создаем метод.
     * 
     * @return string
     */
    public function getNameElement()
    {
        return $this->_nameElement;
    }

    /**
     * Вернет имя класса с которым будем работать.
     * 
     * @return string
     */
    public function getNameClassNameSpace()
    {
        if($this->getSystemNameSpace() === $this->getNameSpace()) {
            // системная директория 
            $class = $this->getSystemNameSpace() . '_Form_Fields';
        } else {
            $class = $this->_nameSpace . '_Form_Fields';
        }
        return $class;
    }
    
    /**
     * Вернет путь к классу с которым будем работать.
     */
    public function getPathClassNameSpace()
    {
        if($this->getSystemNameSpace() === $this->getNameSpace()) {
            // системная директория 
            $path = Arm_Core::getPathLibrary() . $this->getSystemNameSpace() . '/Form/Fields.php';
        } else {
            $path = Arm_Core::getPathModule($this->getNameSpace()) . 'forms/Fields.php';
        }
        return $path;
    }
    
    /**
     * Запуск работы  плагина.
     */
    public function run ($nameElemnt, $nameSpace, $data)
    {
        $this->setData($data);
        $this->setNameSpace($nameSpace);
        $this->setNameElement($nameElemnt);
        $this->setNameMethod($nameElemnt);
        $index = 'Arm_Builder_Fields' . $this->getNameClassNameSpace();
        /*@var $class Zend_CodeGenerator_Php_Class */
        if (!Zend_Registry::isRegistered($index)) { 
            $class = Zend_CodeGenerator_Php_Class::fromReflection(new Zend_Reflection_Class($this->getNameClassNameSpace()));
            Zend_Registry::set($index, $class);
        } else {
            $class = Zend_Registry::get($index);
        }
        if (true === $class->hasMethod($this->getNameMethod())) {
            // метод существует выходим
            return false;
        }
        // Создаем метод и записываем класс
        $method = new Zend_CodeGenerator_Php_Method();
        $method->setName($this->getNameMethod());
        $method->setBody($this->getBody());
        $method->setDocblock($this->getDocblock());
        $class->setMethod($method);
        $file = new Zend_CodeGenerator_Php_File();
        $file->setClass($class);
        file_put_contents($this->getPathClassNameSpace(), $file->generate());
        return true;
    }
    
    /**
     * Вернет имя таблицы, или false если данные элемента не создается
     * для конретно таблици.
     * 
     * @return string|false
     */
    protected function _getTableName()
    {
        if (isset($this->_data['TABLE_NAME']) === true) {
            return $this->_data['TABLE_NAME'];
        }
       return false;
    }
    
    /**
     * Вернет стоковой индефикатор для коментариев, если 
     * элемент создается для таблицы.
     * @return string|null
     */
    protected function _getStrIdFieldTable()
    {
        $table = $this->_getTableName();
            if($table !== false) {
                return Arm_Translate::_('Таблица::поле') . ' ' . $table . '::' . $this->getNameElement() . "\n"; 
            }
         return null;
    }
    
    /**
     * Вернет тело метода
     * 
     * @return string
     */
    abstract public function getBody();
    
    /**
     * Вернет коментарий к методу
     * 
     * @return Zend_CodeGenerator_Php_Docblock|array|string
     */
    abstract public function getDocblock();
    
    

}